package com.zzw.interceptor;

import com.zzw.constant.OrderConstant;
import com.zzw.properties.InterceptorCommonsProperties;
import com.zzw.properties.RequestContextProperties;
import com.zzw.requestcontext.RequestContext;
import com.zzw.utils.IpUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.web.servlet.ModelAndView;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.UUID;

/**
 * @author zzw
 */
public class RequestContextInterceptor implements InternalHandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(RequestContextInterceptor.class);

    private static final ThreadLocal<RequestContext> REQUEST_CONTEXT_THREAD_LOCAL = new ThreadLocal<>();

    private static final String REQUEST_ID = "request-id";

    private final RequestContextProperties requestContextProperties;

    public static RequestContext getRequestContext() {
        return REQUEST_CONTEXT_THREAD_LOCAL.get();
    }

    public RequestContextInterceptor(RequestContextProperties requestContextProperties) {
        this.requestContextProperties = requestContextProperties;
    }

    @Override
    public int getOrder() {
        return OrderConstant.REQUEST_CONTEXT_ORDER;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        LocalDateTime now = LocalDateTime.now();
        String requestId = generateSn();
        MDC.put(REQUEST_ID, requestId);
        String ip = IpUtils.tryGetRealIp(request);
        logger.info("get request，ip:{},request time:{}", ip, now);
        RequestContext requestContext = new RequestContext();
        requestContext.setRequestTime(now);
        requestContext.setIp(ip);
        requestContext.setSn(requestId);
        REQUEST_CONTEXT_THREAD_LOCAL.set(requestContext);
        return InternalHandlerInterceptor.super.preHandle(request, response, handler);
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        InternalHandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("request end,cost time :{}", (ChronoUnit.MILLIS.between(RequestContext.getInstance().getRequestTime(), LocalDateTime.now())));
        try {
            MDC.remove(REQUEST_ID);
            REQUEST_CONTEXT_THREAD_LOCAL.remove();
        } catch (Exception ignore) {

        }
        InternalHandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    private String generateSn() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    @Override
    public InterceptorCommonsProperties getInterceptorCommonsProperties() {
        return requestContextProperties;
    }
}
